#include "yaml.h"
#include "stdio.h"
#include <string>
#include <iostream>
#include <sstream>

template <class T>
static inline void find(YAML::Node config, const std::string &type, T &val)
{
    if constexpr (std::is_same<T, YAML::Node>::value)
    {
        if (config.Type() != YAML::NodeType::value::Scalar && (config[type].Type() == YAML::NodeType::value::Sequence || config[type].Type() == YAML::NodeType::value::Map))
        {
            val = config[type];
            return;
        }
    }
    else
    {
        if (config.Type() != YAML::NodeType::value::Scalar && config[type].Type() == YAML::NodeType::value::Scalar)
        {
            val = config[type].as<T>();
            return;
        }
    }

    switch (config.Type())
    {
    case YAML::NodeType::value::Undefined:
    case YAML::NodeType::value::Null:
    case YAML::NodeType::value::Scalar: // scalar
    {
        break;
    }
    case YAML::NodeType::value::Sequence: // sequence
    {
        for (auto itvv : config)
        {
            find<T>(itvv, type, val);
        }
        break;
    }
    case YAML::NodeType::value::Map: // map
    {
        for (auto itvv : config)
        {
            YAML::Node nNext = itvv.second;
            find<T>(nNext, type, val);
        }
        break;
    }
    default:
        break;
    }
}

YAML::Node load(const std::string &file)
{
    printf("load %s.\n", file.c_str());

    YAML::Node config = YAML::LoadFile(file);
    if (config.Type() == YAML::NodeType::value::Undefined || config.Type() == YAML::NodeType::value::Null || config.Type() == YAML::NodeType::value::Scalar)
    {
        printf("error load %s.\n", file.c_str());
    }

    return config;
}

int main(int argc, char *argv[])
{
    YAML::Node cfg = load("./config.yaml");
    std::cout << cfg << std::endl;

    std::string Q1, Q2, Q3;
    find(cfg, "param", Q1);
    find(cfg, "Id1", Q2);
    find(cfg, "S1", Q3);
    printf("Q1:%s,Q2:%s,Q3:%s\n", Q1.c_str(), Q2.c_str(), Q3.c_str());
    return 0;
}
